Skip to content

Add [FunctionUrl] annotation attribute with CORS support and source generator#2324

Open
GarrettBeatty wants to merge 8 commits intodevfrom
feature/function-url-annotations
Open

Add [FunctionUrl] annotation attribute with CORS support and source generator#2324
GarrettBeatty wants to merge 8 commits intodevfrom
feature/function-url-annotations

Conversation

@GarrettBeatty
Copy link
Copy Markdown
Contributor

@GarrettBeatty GarrettBeatty commented Apr 3, 2026

Add [FunctionUrl] annotation attribute with CORS support and source generator

What is this?

Adds first-class support for Lambda Function URLs to the Lambda Annotations framework. Function URLs give your Lambda function a dedicated HTTPS endpoint without needing API Gateway — ideal for webhooks, simple APIs, and microservices.

Usage

[LambdaFunction]
[FunctionUrl(AuthType = FunctionUrlAuthType.NONE)]
public IHttpResult GetItems([FromQuery] string category, ILambdaContext context)
{
    return HttpResults.Ok(new { items = new[] { "item1", "item2" }, category });
}

This generates a handler that accepts HTTP API v2 payloads and emits a FunctionUrlConfig in your SAM template — no API Gateway resource needed.

CORS support

[FunctionUrl(AuthType = FunctionUrlAuthType.NONE,
             AllowOrigins = new[] { "https://example.com" },
             AllowMethods = new[] { "GET", "POST" },
             AllowHeaders = new[] { "Content-Type" },
             AllowCredentials = true,
             MaxAge = 3600)]

CORS configuration is optional — the Cors block is only emitted when at least one CORS property is set.

Authentication

Two auth modes via FunctionUrlAuthType:

  • NONE — Public endpoint, anyone with the URL can invoke the function
  • AWS_IAM — Only authenticated IAM users/roles can invoke the function

Key points

  • Function URLs only support the HTTP API v2 payload format (APIGatewayHttpApiV2ProxyRequest/Response), so the source generator always uses v2 types — there is no version selection like [HttpApi] has
  • All existing parameter binding ([FromQuery], [FromHeader], [FromBody], [FromRoute]) and IHttpResult returns work out of the box
  • Generates FunctionUrlConfig as a property on the function resource (not as an event source), matching the SAM specification
  • Automatically cleans up FunctionUrlConfig from the template when the attribute is removed
  • Handles switching between [FunctionUrl] and [HttpApi]/[RestApi] seamlessly
  • Detects [FunctionUrl] without [LambdaFunction] and reports a diagnostic error

Related: DOTNET-8569

…oudFormation FunctionUrlConfig generation

- New FunctionUrlAttribute class with AuthType property (NONE/AWS_IAM)
- New FunctionUrlAuthType enum
- Source generator detects FunctionUrlAttribute and maps to EventType.API
- Generated wrapper uses HttpApi V2 request/response types (same payload format)
- CloudFormationWriter emits FunctionUrlConfig on the function resource
- Dependency validation checks for Amazon.Lambda.APIGatewayEvents
- SyntaxReceiver detects missing [LambdaFunction] on [FunctionUrl] methods
- 6 new unit tests for CloudFormation template generation (JSON + YAML)
- AllowOrigins, AllowMethods, AllowHeaders, ExposeHeaders, AllowCredentials, MaxAge properties
- FunctionUrlAttributeBuilder parses all CORS properties from AttributeData
- CloudFormationWriter emits Cors block under FunctionUrlConfig only when CORS properties are set
- 4 new unit tests for CORS generation and no-CORS scenarios
- Remove FunctionUrlConfig from template when [FunctionUrl] attribute is removed
- Clean transition when switching from [FunctionUrl] to [HttpApi] or [RestApi]
- 4 new unit tests for orphan cleanup and attribute switching scenarios
- FunctionUrlExample.cs test source with [FunctionUrl] + [FromQuery] + IHttpResult
- Generated wrapper snapshot using HttpApi V2 payload format
- Serverless template snapshot with FunctionUrlConfig
- Full Roslyn source generator verification test
@GarrettBeatty GarrettBeatty force-pushed the feature/function-url-annotations branch from 5bfe161 to 6d32835 Compare April 3, 2026 15:09
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class Lambda Function URL support to the Lambda Annotations framework, including SAM FunctionUrlConfig emission, optional CORS configuration, and end-to-end tests (unit + integration) to validate generation and invocation behavior.

Changes:

  • Introduces [FunctionUrl] + FunctionUrlAuthType in Amazon.Lambda.Annotations.APIGateway and wires it into the source generator’s discovery/model building.
  • Updates CloudFormation template writing to emit FunctionUrlConfig (and optional Cors) on the function resource and to remove the config when the attribute is removed.
  • Adds generator snapshot tests, CloudFormation writer tests, and a deployed integration test example that calls the Function URL and validates logs/config.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Libraries/test/TestServerlessApp/serverless.template Adds a generated function resource that includes FunctionUrlConfig.
Libraries/test/TestServerlessApp/FunctionUrlExample.cs Adds a sample Lambda handler annotated with [FunctionUrl].
Libraries/test/TestServerlessApp/aws-lambda-tools-defaults.json Updates default stack/bucket naming used by integration deployment.
Libraries/test/TestServerlessApp.IntegrationTests/IntegrationTestContextFixture.cs Discovers and stores the deployed Function URL for integration tests; updates expected function count.
Libraries/test/TestServerlessApp.IntegrationTests/FunctionUrlExample.cs Adds integration tests for invoking the Function URL, validating response/logging/config.
Libraries/test/IntegrationTests.Helpers/LambdaHelper.cs Adds helper to fetch GetFunctionUrlConfig from Lambda.
Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/FunctionUrlTests.cs Adds CloudFormation writer unit tests for Function URL config and CORS emission/removal/switching.
Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs Adds snapshot-based source generator test coverage for Function URL generation.
Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/functionUrlExample.template Adds expected serverless template snapshot for Function URL output.
Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/FunctionUrlExample_GetItems_Generated.g.cs Adds expected generated handler snapshot for a Function URL endpoint.
Libraries/src/Amazon.Lambda.Annotations/APIGateway/FunctionUrlAuthType.cs Introduces auth mode enum for Function URLs.
Libraries/src/Amazon.Lambda.Annotations/APIGateway/FunctionUrlAttribute.cs Introduces [FunctionUrl] attribute including optional CORS properties.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs Emits/removes FunctionUrlConfig and emits optional Cors block for Function URLs.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Validation/LambdaFunctionValidator.cs Ensures required dependency on Amazon.Lambda.APIGatewayEvents when [FunctionUrl] is used.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs Registers full type names for new Function URL types.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs Treats [FunctionUrl] as a “secondary attribute” requiring [LambdaFunction] for diagnostics.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs Forces Function URL handlers to use HTTP API v2 request/response types.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/EventTypeBuilder.cs Classifies [FunctionUrl] as an API-type event for validation/behavior.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FunctionUrlAttributeBuilder.cs Builds the FunctionUrlAttribute model from Roslyn AttributeData.
Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs Adds [FunctionUrl] to attribute model building pipeline.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +11 to +16
NONE,

/// <summary>
/// IAM authentication. Only authenticated IAM users and roles can invoke the function.
/// </summary>
AWS_IAM
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FunctionUrlAuthType introduces enum members in ALL_CAPS (NONE, AWS_IAM), which is inconsistent with the rest of the public enums in this package (e.g., LambdaHttpMethod.Get, HttpApiVersion.V2). Consider using PascalCase member names (e.g., None, AwsIam) and mapping to the SAM-required strings in the template writer (so public API stays idiomatic while still emitting NONE/AWS_IAM).

Suggested change
NONE,
/// <summary>
/// IAM authentication. Only authenticated IAM users and roles can invoke the function.
/// </summary>
AWS_IAM
None,
/// <summary>
/// IAM authentication. Only authenticated IAM users and roles can invoke the function.
/// </summary>
AwsIam

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it should be all caps

GarrettBeatty and others added 3 commits April 6, 2026 13:58
…/Attributes/FunctionUrlAttributeBuilder.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@@ -0,0 +1,18 @@
namespace Amazon.Lambda.Annotations.APIGateway
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically function url is completely different than api gateway but uses the same api gateway v2 response type, so i kept it in the same namespace for now

@GarrettBeatty GarrettBeatty requested review from normj and philasmar April 6, 2026 18:22
@GarrettBeatty GarrettBeatty marked this pull request as ready for review April 6, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants